package cn.silver.framework.mybatis.utils;

import cn.silver.framework.core.exception.UtilException;
import cn.silver.framework.core.utils.StringUtils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author zhouxiaobo
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class SqlUtils {
    /**
     * 数据库关键词
     */
    public static final String SQL_REGEX = "select |insert |delete |update |drop |count |exec |chr |mid |master |truncate |char |and |declare ";
    /**
     * 仅支持字母、数字、下划线、空格、逗号、小数点（支持多个字段排序）
     */
    public static final String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";

    /**
     * 仅支持字母、数字、下划线
     */
    public static String PROPERTY_PATTERN = "[a-zA-Z0-9_]+";

    /**
     * 获取数据库中的名字：驼峰转下划线
     *
     * @param propertyName 属性名
     * @return
     */
    public static String getJdbcName(String propertyName) {
        if (!propertyName.matches(PROPERTY_PATTERN)) {
            throw new UtilException("参数不符合规范，只能包含字母和数字");
        }
        Pattern compile = Pattern.compile("[A-Z]");
        Matcher matcher = compile.matcher(propertyName);
        StringBuilder buffer = new StringBuilder();
        while (matcher.find()) {
            matcher.appendReplacement(buffer, "_" + matcher.group().toLowerCase());
        }
        matcher.appendTail(buffer);
        return buffer.toString();
    }

    /**
     * 获取属性名：下划线转驼峰
     *
     * @param jdbcName 数据库字段名
     * @param firstFlg 首字母是否需要大写
     * @return
     */
    public static String getPropertyName(String jdbcName, boolean firstFlg) {
        if (!jdbcName.matches(PROPERTY_PATTERN)) {
            throw new UtilException("参数不符合规范，只能包含字母和数字");
        }
        if (!jdbcName.contains(StringUtils.UNDERLINE)) {
            return jdbcName;
        } else {
            String[] split = StringUtils.split(jdbcName, StringUtils.UNDERLINE);
            StringBuilder buffer = new StringBuilder();
            for (int i = 0; i < split.length; i++) {
                if (firstFlg && i == 0) {
                    buffer.append(split[i].toLowerCase());
                } else {
                    buffer.append(split[i].substring(0, 1).toUpperCase()).append(split[i].substring(1).toLowerCase());
                }
            }
            return buffer.toString();
        }
    }

    public static String escapeOrderBySql(String value) {
        if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value)) {
            throw new UtilException("参数不符合规范，不能进行查询");
        }
        return value;
    }

    public static boolean isValidOrderBySql(String value) {
        return value.matches(SQL_PATTERN);
    }

    public static void filterKeyword(String value) {
        if (StringUtils.isEmpty(value)) {
            return;
        }
        String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
        for (String sqlKeyword : sqlKeywords) {
            if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1) {
                throw new UtilException("参数存在SQL注入风险");
            }
        }
    }
}
